<?php

1->微服务常用组件
   - Eureka (服务治理)
   - Ribbon (负载均衡)
   - Hystrix (服务容错, 降级/熔断)
   - Feign (服务间调用)
   - Config (分布式配置中心)
   - BUS (消息总线)
   - Gateway (服务网关)
   - Sleuth (调用链追踪)
   - Stream (消息驱动)
   - Sentinel (消息限流)


2->为什么要使用微服务 (前身)
   相对'单体应用'来说
   - 数据访问杂乱
     同一个war包内，在数据访问层面没有划分领域模型，比如说我们有User、Product和Order三张表，对于不同的Service来说，
     都通过直接访问数据库的方式来获取数据。这种做法有几个显而易见的缺点:
     . '数据模型变更'
        拿Order表来说，如果某一天我的Data Model发生了重大变更，比如说引入了“子订单”的概念，原先的数据模型不能再很好地支持业务，
        必须重构Order订单表，与此同时，还要兼容老的订单结构。这种情况下你能贸然改动数据模型吗？恐怕不行，原因就是这个Order表被这个系统中的各个服务引用到了，
        你的改动可能会破坏其他服务的功能。

        对于传统的应用结构来说，一丁点数据结构的改变都会引起很大的影响。如果数据模型的变动是必须的，那我们如何解决这种情况呢？
        很简单，通过微服务架构在各个服务之间做好隔离，将Data Model的影响带来的业务复杂度隔离在当前微服务中，划分好领域模型，
        上下游服务只要对接微服务的接口就可以，领域模型驱动不用依赖底层数据结构的变更。

     . '底层组件变更'
        假如现在我要对Product表的数据访问规则做一个变更，比如引入MyCat分库分表，或者对热点数据的访问加上缓存读写的步骤。
        那么意味着上下游所有访问Product表的业务，都需要连带着做同样的改动。

        理论上来说，我们应该尽可能对业务层屏蔽底层组件的变更，在传统的分布式应用中非常难以办到，但是在微服务架构下却没有那么困难，
        因为微服务间的访问依赖'API接口+业务模型'，我们只要在当前微服务中把这种底层组件的变更处理好，对上下游其他服务来讲这个变更其实是无感知的，
        因为在微服务接口暴露出的业务模型并不会有什么变化。

     . '回滚'
        回滚对于传统的单war包分布式系统来说是个噩梦，好不容易等到了发布窗口，各个团队牟足了劲把所有变更都发布了出去，
        结果因为其中某个小改动引发的问题，导致全部回滚。又要苦苦等待下一个发布窗口。

        在微服务架构中，回滚只局限在某个微服务的范围内，只要把出问题的应用回滚就好了，不会影响上下游其他应用的发布节奏。


4->微服务优缺点
   - '优点'
      1、快速响应变更: 单一职责、独立部署
      2、独立扩展: 边界清晰，不过度受制于技术栈
      3、精粒度业务控制: 降级熔断、局部限流
      4、面向业务/领域模型: 不依赖数据模型，易于抽象

   - '缺点'
      1、部署结构复杂: 模块众多，一堆额外组件
      2、依赖平台支撑: 依赖微服务组件，增加研发成本
      3、分布式问题: 数据一致性，一场补偿
      4、拆分水平: 微服务基于业务进行拆分，如果对业务了解不够深入，粒度过粗、过细都很麻烦。


5->微服务架构面临的问题
   1、服务治理与负载均衡
   2、服务容错
   3、配置管理
   4、服务网关
   5、调用链路追踪
   6、消息驱动
   7、限流


6->SpringCloud整体架构
   -) '服务治理 -> Eureka'
       Spring Cloud提供了三款服务治理的组件，分别是 'Eureka', 'Consul' 和 'Nacus'，从这三足鼎立的态势里我们就能猜到，
       在服务治理领域的背后一定有那么一段恩怨情仇。没错，这三个组件其实是由'三个不同的公司或组织'来研发的.

       在Spring Cloud的架构中，服务治理是其中不可或缺的核心环节，它包含了服务从注册到销毁的整个生命周期的管理。
       用一句话来说，服务治理确保了调用方可以准确的向'可用的服务节点'发起调用.

   -) '负载均衡 -> Ribbon'
       Ribbon是Spring Cloud中负责负载均衡的组件，Ribbon的一大优势是它能够和各个Spring Cloud组件'无缝集成'，而且十分灵巧轻便又具备高可扩展性。

       负载均衡框架是起到分散服务器压力的作用，可以这么说，没有负载均衡技术的服务器集群就不能叫做集群，只有借助负载均衡技术，
       集群才能够借助服务节点的规模效应发挥出优势。

   -) '消息间调用 -> Feign'
       对于原生态的HTTP调用来说，从Java代码里发起调用并且构造消息体和Header是一件非常麻烦的事情，
       考虑到Spring Cloud的服务治理组件也是基于HTTP的，因此特别需要一款简化服务调用的组件。
       Feign的出现就是为了解决这个问题，我们可以借助Feign的代理机制，像调用一个接口方法一样发起远程HTTP调用。

   -) '服务容错 -> Hystrix'
       Hystrix是目前Spring Cloud中应用最广泛的服务容错组件，服务容错从宏观上来解释，就是尽可能降低服务异常所带来的影响。
       我们经常听到两个词叫做'降级'和'熔断'，降级很好理解，现在大家都会打趣的说“消费降级”，就是说降低咱自己的消费水平,在服务容错这里其实是一个道理，
       降级: 就是退而求其次，在异常发生之后选一种备选方案继续提供服务。
       熔断: 则是指在异常达到某个临界值以后，直接切断服务通路，将用户请求统统导向降级逻辑中。

   -) '分布式配置中心和消息推送组件 -> Config & Bus'
       Spring Cloud借助Config组件来集中管理集群中所有服务节点的配置，它是一个中心化的配置管理中心，
       可以采用包括'Github、Database'等多种持久化方案来保存配置信息，将你的微服务从繁重的配置工作中解脱出来。
       利用Config组件我们可以轻松玩转环境隔离、配置推送和配置项动态刷新。

       提到配置属性的刷新，就不得不说到Spring Cloud中的另一个组件Bus，它承担了批量通知和推送配置变更的工作，
       而且我们可以通过扩展Bus的事件，实现'消息广播'的应用场景。

   -) '服务网关 -> Gateway & Zuul'
       服务网关是微服务的'第一道关卡'，目前Nginx是应用最广泛的反向代理技术，在各个大厂的核心业务系统中都有大量应用，
       不过Nginx可不是使用Java来配置的，使用和配置Nginx需要掌握它的语法树。Spring Cloud则为广大的Java技术人员提供了更加'编程友好'的方式来构建网关层，
       那就是'Gateway和Zuul'网关层组件。我们可以通过Java代码或者是yml配置文件的方式编写自己的路由规则，
       并通过'内置过滤器'或'自定义过滤器'来实现复杂的业务需求（比如在网关层做令牌验证）。Gateway本身也集成了强大的限流功能，
       结合使用'Redis+SpEL'表达式，可以对业务系统进行精准限流。

   -) '服务链路追踪 -> Sleuth'
       微服务的一大特点就是完成一个业务场景所需要调用的'上下游链路非常长'，比如说一个下单操作，后台就要调用商品、订单、营销优惠、履约、消息推送、支付等等
       一大家子微服务，任何一个环节出错可能都会导致下单失败。那同学们如何在一个调用链路中定位到出问题的环节呢？生产环境可不是我们的开发机器，
       不能为所欲为的做线上debug，那我们只能依靠日志线索。

       Sleuth是Spring Cloud提供的调用链路追踪组件，它进行线上问题排查必不可少的关键环节，单就Sleuth来说，
       它就是在一整条调用链路中打上某个标记，将一个api请求所调用的所有上下游链路串联起来。如果从宏观的角度来说，调用链追踪还涉及到日志打标、
       调用链分析、日志收集、构建搜索Index等等流程，我们在本章中将通过'Sleuth+Zipkin+ELK'（Elasticsearch, Logstash，Kibana）这五种技术结合使用，
       玩转调用链路追踪。

   -) '消息驱动 -> Stream'
       Kafka和RabbitMQ 是目前应用最广泛的消息中间件，很多异步调用场景底层都依赖于消息组件，比如说电商场景中的商品批量发布，
       或者下单成功后的邮件通知系统等等。Stream是Spring Cloud为我们提供的消息驱动组件，它代理了业务层和底层的物理中间件的交互，
       至于底层中间件是Kafka还是RabbitMQ，对业务层几乎是无感知的。借助Stream我们不仅可以轻松实现组播（组内单播）和广播场景，
       同时Stream还提供了对异常处理的丰富支持。

   -) '防流量卫兵 -> Sentinel'
       Sentinel是'阿里巴巴'开源的一款主打“流量控制”的组件，它秉承了阿里系组件十八班武艺样样精通的风格，与Spring Cloud、Dubbo、
       甚至gRPC都可以很好的集成，在分布式流量控制（包括秒杀场景的突发流量场景）、熔断、消息驱动下的'削峰填谷'等各个场景下都有稳定发挥，
       要知道它可是在背后默默支撑双十一流控业务的顶梁柱。


7->SpringCloud核心组件介绍(Netflix + Alibaba套件)
   引子: 上面介绍了SpringCloud的各个组件, '看似'其乐融融, 实则有'三股势力'在暗暗较劲!
   -) 'Netflix'
       是先有Spring Cloud还是先有Netflix？
       这是一个好问题。Netflix是一家大名鼎鼎的互联网传媒公司，但为什么它在开源软件领域有这么大的名声呢？这就不得不说起它和Spring Cloud的渊源了。

       很久很久以前，天和地还没有分开，宇宙混沌一片。有个叫Netflix的公司，在这混沌之中，拿自身的业务动手，开启了一段微服务的改造之旅。
       在这段漫长的过程中，沉淀出了一系列优秀的微服务组件，比如大名鼎鼎的Eureka，Hystrix，Zuul等等，
       这些组件经过Pivotal的'一系列封装'以后就构成了初代目Spring Cloud。

       目前Spring Cloud Netflix组件库是Spring Cloud中最受欢迎的项目，并且还拥有最广泛的群众基础，这么说吧，10个用Spring Cloud的公司，
       有八九个都会选用Netflix组件库全家桶来构建自己的技术栈。听到这，同学们可能会问，难道Spring Cloud里还有其他的组件库吗？那我们就往下看。

   -) '阿里巴巴'
       阿里近些年开源的步子迈的很大，都说步子迈得大容易扯着裆，不过凭借'阿里996+鸡血文化'的加持，用互联网行业特有的'糙快猛'的精神，
       近几年在开源软件上不断开疆扩土，发展速度和规模都是可圈可点。

       目前开源领域一大热门当属Spring Cloud，尽管前面有Netflix组件库占尽天时地利，可是不妨碍阿里巴巴集团一贯怼天怼地的做派。
       这不，Spring Cloud大家族中又添新丁，那就是–'Spring Cloud Alibaba'组件库。

       从目前的势头来看，Alibaba组件库还是呈现一路高歌猛进的态势，其中多款组件已经站上擂台和Netflix组件展开直接竞争。
       得益于阿里集团的福报文化，加班不要命的码农们给这些组件添加了各种业务功能，从我个人使用这两个组件的感受来说，
       Netflix: 组件相对来说比较'纯粹和纯净';
       Alibaba: 组件似乎透出一股'KPI导向'的味道（恨不得把能想到的功能全塞进去）。
       本章课程我们将以Netflix组件为主，同时也会重点介绍几个Alibaba组件库的组件。

   -) 'Spring Open Source'
       这最后一股势力就是Spring自个儿了，由Spring自己独家挂牌的开源组件，可以说是“原配”组件了。都说原配的才是最好的，
       不过在上面两个重量级组件库面前还真不好说。同学们经常会看到这样一个情况，在某个领域中这三家的组件会扎堆出现。
       比如服务治理，这三家各自都有一个独立组件，想想大家都是Spring Cloud一家子，为何还整出了一副三足鼎立的态势呢？后续再说...

   - '势力范围'
      +=================+=============================+=============================+=============================+
      |                 |                             |                             |                             |
      |    应用领取名称   |           Netflix           |         Alibaba组件          |      Spring或其他开源厂商     |
      |                 |                             |                             |                             |
      +=================+=============================+=============================+=============================+
      |     服务治理     |            Eureka           |     Nacos, Dubbo(RPC框架)    |            Consul           |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     负载均衡     |     Ribbon(loadbalancer)    |                             |                             |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     服务调用     |   Feign (后划归为openfeign)  |                              |                             |
      |                |spring-cloud-starter-openfeign|                             |                             |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     服务容错     |  Hystrix+Turbine+Dashboard  |                             |                             |
      +-----------------+-----------------------------|          Sentinel           |                             |
      |     限流        |                              |                             |     Gateway支持网关层限流     |
      +-----------------+-----------------------------+-----------------------------|                             |
      |     服务网关     |            Zuul             |                             |                             |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     配置管理     |          Archaius           |       Alibaba Cloud ACM     |            Config           |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     消息总线     |                             |                             |             Bus             |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     调用链路追踪  |                             |                             |           Sleuth            |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     消息驱动组件  |                             |  RocketMQ(Java写的消息中间件) |  Stream(对接Kafka,RabbitMQ)  |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     任务调度     |                             |   Alibaba Cloud SchedulerX  |      spring-cloud-task      |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+
      |     其他         |        Sidecar(跨语言)       | Seata(分布式事务),SMS(短信服务)|                             |
      +-----------------+-----------------------------+-----------------------------+-----------------------------+

   - '说明'
      从上面的表格中可以看出，在大多数的领域当中，我们都有多与一种的解决方案，而且各个组织在不同领域发力程度也不一样。
      我们在实际的研发当中不会只盯着一个组件库用，而是结合使用来自不同组织开发的组件，这样才能发挥Spring Cloud的最强功力。

      同学们可能注意到了，阿里巴巴组件库传达出了一股不小的野心，它的很多的组件都和阿里云（Alibaba Cloud）紧密关联了起来，
      甚至连Nacos都有一股“强推Dubbo”的味道，看上去像是在大力推广阿里集团自己的技术栈，似乎并不打算全心全意服务于Spring Cloud原生的生态体系。
      所以从我个人角度来说，并不太喜欢这种比较'功利'和'KPI导向'的价值观。


8->SpringCloud发展史
   -) '发展史'
                          (2016.5)                                      (2017.4)
       Angel -------------> Brixton -------------> Camden -------------> Dalston -------------> Edgware
      (2015.3)                                    (2016.9)                                     (2017.11)
                                                                                                  |
                                                (2019.1)                                          |
                    Hoxton ... <-------------- Greenwich <-------------- Finchley <---------------+
                                                                         (2018.6)


   -) '版本上线流程 - F'
       Milestone版 ---------> RC版(到RC2 / Release Candidate) ---------> Release版 ---------> SR正式版本(SR1 ~ SR4)
       (始于2017)                      (2018.4 ~ 5)                      (2018.6)                历时一年
       SRx: 正式发布并稳定的版本.


   -) 'Spring Cloud 维护策略'
       多个大版本交叉迭代 < 1年一版 -----------+                        +------------ 即使大版本更新, 上一个版本依然维护很长时间
                                           |                        |
                                           +----- Spring Cloud -----+
                                           |                        |
                社区积极解决issue -----------+                        +------------ 早期升版'各种坑淹死', 如今升版轻轻松松


   -) '升版利弊'
       . 技术栈+ / 可扩展性+
       . Bug Fix安全性补丁
       . 新组件新功能, 可以玩新的业务场景
       - 对当前业务的影响
       - 上线游系统兼容性
       - 替换成本, 开发资源, 运维成本

   -) '推荐策略'
       Tech Stack Review (半年度/年度) -----------+                        +------------ 持续关注新的大版本 (新功能, 新组件)
                                                |                        |
                                                +----- 项目技术栈升级 -----+
                                                |                        |
               只采用SR发布版, 绝不冒进 -----------+                         +------------ POC先行, 全链路测试 + 回滚计划
                                                  '有更新 - 但不要追新'


9->Eureka核心流程
    - 服务注册
    - 服务发现
    - 心跳与续约
    - 服务下线
    - 剔除和自保


10->服务治理
    高可用性:
    换成通俗易懂的说法就是“当一只打不死的小强”，在服务治理麾下的所有微服务节点，不论是被闪电击中还是被挖掘机铲断了电源，
    即使战至最后一个存活节点，服务治理框架也要保证服务的可用性。

    分布式调用:
    微服务的节点通常散落在不同的网络环境中，大型互联网公司甚至会使用两地三机房或跨洲际机房做异地容灾。
    这就要求服务治理框架具备在复杂网络环境下准确获知服务节点网络地址（IP，端口以及服务名称）的能力。作为服务消费者，
    就可以借助服务治理框架的精准制导能力，向服务节点发起请求。一只穿云箭，千军万马来相见。

    生命周期管理:
    万物都在轮回之中，在Spring的世界更是如此。微服务也把自己平凡而充实地一生，交给了服务治理框架，从服务上线、持续运行直到临终关怀，
    服务治理始终贯穿整个微服务生命周期。

    健康度检查:
    微服务的节点都是任劳任怨的执行996，当然，如果一个节点因为任何原因不再996的亲勤工作，那就不再是哥的兄弟了。
    服务治理框架要精准识别这些节点，将其从自己的兄弟会中剔除。


11->服务治理选型
    -) 'CAP'
        . Consistency:
          一致性  (分布式环境中所有的节点每一个节点保存数据的副本. 一致性数据的一致性。指的是《强一致性》).
          强一致性: 更新操作之后，后续访问请求都能取得到更新之后的值。
          弱一致性: 全部访问请求都拿不到数据，一部分请求拿不到数据。
          最终一致性: 所有的数据副本中的值都会保持一致性。

        . Availability: 可用性, 保证每个请求不管成功或者失败都有响应. (99.999%    宕机 < 5min)
        . Partition tolerance: 分区容错性, 系统中任意信息的丢失或失败不会影响系统的继续运作.

        注意: 分布式系统只能三选二 ，不能全占。

    - '服务治理三大门派'
       Eureka: 老大哥 (Netflix), 一致被模仿, 从未被超越!
       Nacos:  后起之秀 (阿里巴巴)
       Consul: 同门师弟 (SpringCloud开发)

    - '切磋'
       +===============+=====================+======================+===============+
       |               |      Eureka         |      Consul          |     Nacos     |
       +===============|=====================+======================+===============+
       |     一致性     |     弱一致性(AP)     |    弱一致性(AP)        |    AP / CP    |
       +---------------+---------------------+----------------------+---------------+
       |      性能      |         快          | 慢(RAFT协议Leader选举) |       快      |
       +---------------+---------------------+----------------------+---------------+
       |    网络协议    |         HTTP        |       HTTP & DNS     | HTTP&DNS&UDP  |
       +---------------+---------------------+----------------------+---------------+
       |    应用广度    |       目前主流        |       目前非主流      | 稳重有升尚待观察 |
       +---------------+---------------------+----------------------+---------------+

    - '阿里命名'
       . 鹰眼
       . 德鲁伊
       . 迈巴赫
       . 天梯
       规则: 不管是做什么的, 一定要让别人不知道是做什么的, 才显得'装, 有逼格'!


12->注册中心解决方案
    A- 由注册中心主动访问网络节点中的所有机器 (Eureka, 你别动, 我来)
    B- 注册中心坐等服务节点上门注册 (Dubbo, 你若盛开-蝶自来)

    'A - 弊端'
     模型复杂:
     网络环境浩如烟海，轮询每个节点的做法通常是注册中心发局域网广播，客户端响应的方式，这种方式就像你对着全世界喊我爱你，顿时感到有种无力感。
     现实中对于跨局域网的分布式系统来说，响应模型更加复杂.

     网络消耗大:
     整个网络环境里会掺杂大量非服务节点，这些节点无需对送达的广播请求做出响应，这种广播的模式无疑增加了网络通信成本。

     服务端压力大:
     不仅要求注册中心向网络中所有节点主动发送广播请求，还需要对客户端的应答做出响应，一个担子两头挑。
     考虑到注册中心的节点数远远少于服务节点，我们要尽可能地减轻服务中心承载的业务。

    'B - 好处'
     省心: 对于网络中其它非服务节点来说不会产生任何无效请求.
     省时: 省去了广播环节大时间, 使注册效率大大提高.
     省力: 节省了大量网络请求的开销.

    '注册中心'
     在茫茫世界中游荡的戈多，是如何找到流浪汉去报道的呢？当然是靠着我们开发人员作为上帝视角预先告诉了他们流浪汉的地址，
     这个地址包含了三个维度的信息，分别是'Region', 'Zone'和'URL'。
     Region: 代表地理上的分区.
     Zone:
     则是这个分区下的机房, 大多数情况下我们的配置中心只存在一个机房，这时配置URL就好了.
     比如: http://localhost:20000/eureka/
     这是注册中心的IP地址，同时Eureka会为我们指定一个默认的Region和Zone。
